package logiclib

import (
	"errors"
	"net/http"
	"net/rpc"
	"sync"
	"time"

	"github.com/wonderivan/logger"
)

// GetCommandCallback Callback Func
type GetCommandCallback func(name *string, cmd *CMDStruct)

// GetInfoCallback Callback Func
type GetInfoCallback func(cmd *CMDStruct, res *ResponseStruct)

// GetCommandCallbackHandle Callback Func
var GetCommandCallbackHandle GetCommandCallback

// GetInfoCallbackHandle Callback Func
var GetInfoCallbackHandle GetInfoCallback
var _lockers map[string]*CMDLocker

// GetLockers 获取及初始化lockers
func GetLockers() map[string]*CMDLocker {
	if _lockers == nil {
		_lockers = make(map[string]*CMDLocker, 0)
	}
	return _lockers
}

// GetLockerByName 根据名字获取locker
func GetLockerByName(name string) *CMDLocker {
	if lockers := GetLockers(); lockers != nil {
		if locker, ok := lockers[name]; ok {
			if locker == nil {
				lockers[name] = &CMDLocker{Name: name, Command: make(chan string), IsLocked: false}
			}
			return locker
		}
	}
	return nil
}

// LockByName 根据名字locker
func LockByName(name string, onlyOne bool) string {
	if locker := GetLockerByName(name); locker != nil {
		locker.Mutex.Lock()
		if onlyOne && locker.IsLocked {
			oldmutex := &locker.Mutex
			locker.UnLock("STOP")
			lockers := GetLockers()
			locker = &CMDLocker{Name: name, Command: make(chan string), IsLocked: false}
			locker.Mutex.Lock()
			//locker.Mutex.Lock()
			//defer locker.Mutex.Unlock()
			lockers[name] = locker
			oldmutex.Unlock()
			locker.Mutex.Unlock()
			return locker.Lock()
		}
		locker.Mutex.Unlock()
		return locker.Lock()
	}
	lockers := GetLockers()
	locker := &CMDLocker{Name: name, Command: make(chan string), IsLocked: false}
	locker.Mutex.Lock()
	lockers[name] = locker
	locker.Mutex.Unlock()
	return locker.Lock()
}

// UnLockByName 根据名字locker
func UnLockByName(name string, command string) bool {
	if locker := GetLockerByName(name); locker != nil {
		locker.Mutex.Lock()
		if locker.IsLocked {
			locker.UnLock(command)
			locker.Mutex.Unlock()
			return true
		}
		locker.Mutex.Unlock()
		return true
	}
	return false
}

// UnLockAll 全部解锁
func UnLockAll(command string) bool {
	if lockers := GetLockers(); lockers != nil {
		for _, value := range lockers {
			value.UnLock(command)
		}
		return true
	}
	return false
}

// CMDLocker 用于等待命令返回的等待锁
type CMDLocker struct {
	Mutex    sync.Mutex
	Name     string
	Command  chan string
	IsLocked bool
}

// Lock 锁住
func (_this *CMDLocker) Lock() string {
	_this.IsLocked = true
	res := <-_this.Command
	return res
}

// UnLock 解锁
func (_this *CMDLocker) UnLock(command string) {
	_this.Command <- command
	_this.IsLocked = false
}

// CMDStruct 命令结构体
type CMDStruct struct {
	Name    string
	Command string
	Param   string
}

// ResponseStruct 响应结构体
type ResponseStruct struct {
	Name     string
	Response string
	Result   string
}

// RPCManager 服务启停管理
type RPCManager struct {
	//ServiceName string
	//ServiceDis  string
}

// GetCommand 向服务器获取执行命令
func (_this *RPCManager) GetCommand(name *string, cmd *CMDStruct) error {
	if GetCommandCallbackHandle != nil {
		//LockByName(*name, true)
		GetCommandCallbackHandle(name, cmd)
		return nil
	}
	return errors.New("命令没有执行主体回调")
}

// GetInfo 向服务器获取信息
func (_this *RPCManager) GetInfo(cmd *CMDStruct, res *ResponseStruct) error {
	if GetInfoCallbackHandle != nil {
		GetInfoCallbackHandle(cmd, res)
		return nil
	}
	return errors.New("命令没有执行主体回调")
}

// RPCClientManager 服务启停管理
type RPCClientManager struct {
	//ServiceName string
	//ServiceDis  string
	rpcip         string
	lastNoConTime time.Time
}

// Init 初始化
func (_this *RPCClientManager) Init() {}

// Start 初始化
func (_this *RPCClientManager) Start() {
	//获取输入的地址是获取输入得 os 数据的 第一个位置的值
	//_this.rpcip = "192.168.3.117:8087"
	_this.lastNoConTime = time.Now()
	cfgManager := new(ConfigFileBase)
	confs := cfgManager.LoadPortCfg()
	port, res := cfgManager.GetValueFromKey(confs, "rpc")
	if !res {
		port = "8087"
	}
	_this.rpcip = "127.0.0.1:" + port
}

// GetClient 获取远程客户端
func (_this *RPCClientManager) GetClient() *rpc.Client {
	client, err := rpc.DialHTTP("tcp", _this.rpcip)
	if err != nil {
		tmpNow := time.Now()
		if tmpNow.Sub(_this.lastNoConTime) > 30*time.Second {
			logger.Warn("RPC客户端连接异常：", err)
			_this.lastNoConTime = tmpNow
		}
		return nil
	}
	return client
}

// GetCommand 向服务器获取执行命令
func (_this *RPCClientManager) GetCommand(name *string) *CMDStruct {
	client := _this.GetClient()
	if client != nil {
		defer client.Close()
	}
	cmd := new(CMDStruct)
	if client != nil {
		client.Call("RPCManager.GetCommand", name, cmd)
		return cmd
	}
	return nil
}

// GetInfo 向服务器获取信息
func (_this *RPCClientManager) GetInfo(cmd *CMDStruct) *ResponseStruct {
	client := _this.GetClient()
	if client != nil {
		defer client.Close()
	}
	res := new(ResponseStruct)
	if client != nil {
		client.Call("RPCManager.GetInfo", cmd, res)
		return res
	}
	return nil
}

// Stop 初始化
func (_this *RPCClientManager) Stop() {}

// RPCServerManager 服务启停管理
type RPCServerManager struct {
	//ServiceName string
	//ServiceDis  string
}

// Init 初始化
func (_this *RPCServerManager) Init() {}

// Start 初始化
func (_this *RPCServerManager) Start() {
	//arith:=new(Arith)
	//arith=== 0xc04204e090
	//fmt.Println("arith===",arith)

	cfgManager := new(ConfigFileBase)
	confs := cfgManager.LoadPortCfg()
	port, res := cfgManager.GetValueFromKey(confs, "rpc")
	if !res {
		port = "8087"
	}
	rpcManager := new(RPCManager)
	rpc.Register(rpcManager)
	//HandleHTTP将RPC消息的HTTP处理程序注册到Debug服务器
	//DEFAUTUPCPATH和Debug调试路径上的调试处理程序。
	//仍然需要调用http.Services（），通常是在GO语句中。
	rpc.HandleHTTP()
	err := http.ListenAndServe(":"+port, nil)
	if err != nil {
		logger.Fatal(err)
	}
}

// Stop 初始化
func (_this *RPCServerManager) Stop() {

}
